[Rust] Discordのbotを作ってみる [Serenity]
Introduction
私はクラスメソッドで、10年以上リモートワークで作業しているのですが、
メンバーとのやり取りはほとんどSlackでやっています。
しかし、仕事以外ではここ数年、Discordを使う機会が増えてきました。
どうせならbotでもつくってみたいなーと思っていたところ、よい記事があったので、
これを参考にDiscordのシンプルなbotをRustで作成してみます。
Discord?
Discordは、オープンなコミュニティの色合いが強いチャットサービスです。
テキストチャットや通話、ビデオミーティングなどの機能をもってます。
そして、botとはDiscordの拡張機能みたいなものです。
Discordサーバに任意のbotを招待することで、そのbotの機能が使えるようになります。
ちょっと前に話題になった、画像生成AIのMidjourneyもDiscordのbotとして提供されてました。
Environment
- OS : MacOS 12.4
- Rust : 1.62.1
※ M1 Mac(2020)にて動作確認
Setup Discord bot
Discordアカウントの登録
Discordのアカウントがない人は、ここで必要事項を記述して
アカウントを登録しておきましょう。
ログインしたら画面左のサーバ追加ボタンから、
bot動作確認用の適当なサーバを作成しておきます。
botを登録する
まずはbotをDiscordに登録します。
ここへアクセスし、New Applicationボタンを押して
新しいアプリケーションを作成します。
名前を適当に決め、チェックボックスにチェックをつけてCreateボタンを押す。
botのアイコンや情報について設定します。
ここでApplication IDが表示されているので、覚えておきましょう。
サイドバーのメニューから「Bot」を選択します。
ここでは表示名を決めることができます。
また、後で使用するのでReset Tokenボタンを押してトークンを覚えておきます。
そして、bot送られたメッセージから情報を取得するために、
画面下へスクロールし、「MESSAGE CONTENT INTENT」にチェックをつけ、
「Save Changes」ボタンを押して設定を保存します。
次に、下記URLをブラウザでアクセスし、botを認証します。
<Application ID>のところはさきほどコピーしたApplication IDに置き換えてください。
https://discord.com/oauth2/authorize?client_id=<Application ID>&scope=bot&permissions=8
下記画面が表示されるので、作成したサーバーを選択して「はい」を押します。
これでbotが作成されました。
bot追加のメッセージが表示され、画面右に作成したbotが出てきてます。
(オフラインですが)
bot実装前の準備
画面下の歯車アイコンから詳細設定を選択し、「開発者モード」をオンにしておきます。
↑をしておくと、サーバのコンテキストメニューからIDをコピーできたり、bot開発に役立つ機能が追加されます。
Create bot with Rust
botの登録ができたので、実装していきます。
まずは必要なツールやライブラリをインストールします。
cargo-shuttleのインストールとプロジェクト作成
cargo-shuttleはサーバレスWebプラットフォームであるshuttle上に
Webアプリケーションをデプロイするためのコマンドラインツールです。
cargo installでインストールします。
% cargo install cargo-shuttle
Serenity は、Discordのbot用ライブラリです。
下記のようにcargo-shuttleを使って、shuttleへデプロイできる
Serenityを使ったプロジェクトを作成できます。
% cargo shuttle init --serenity
コード実装
まずはプロジェクトのルートにSecrets.tomlファイルを作成し、
↓のように記述します。
DISCORD_TOKEN="<Reset Tokenで取得したトークン>" DISCORD_GUILD_ID="<コンテキストメニュー→サーバIDをコピー でコピーしたID>"
src/lib.rsを、下記のように修正します。
use log::info; use serenity::async_trait; use serenity::model::gateway::Ready; use serenity::model::prelude::*; use serenity::prelude::*; use serenity::model::prelude::interaction::Interaction::ApplicationCommand; use serenity::model::interactions::*; use shuttle_service::error::CustomError; use shuttle_service::SecretStore; use sqlx::PgPool; struct Bot; #[async_trait] impl EventHandler for Bot { async fn ready(&self, ctx: Context, ready: Ready) { info!("{} is connected!", ready.user.name); let guild_id = GuildId(<DISCORD_GUILD_ID>); //コマンドを登録 let commands = GuildId::set_application_commands(&guild_id, &ctx.http, |commands| { commands.create_application_command(|command| { command.name("hello").description("Say hello") }).create_application_command(|command| { command.name("bye").description("Say Good Bye") }) }) .await .unwrap(); info!("{:#?}", commands); } async fn interaction_create(&self,ctx: Context,interaction: serenity::model::interactions::Interaction) { if let ApplicationCommand(command) = interaction { let response_content = match command.data.name.as_str() { "hello" => "hello!!".to_owned(), "bye" => "good bye!!".to_owned(), command => unreachable!("Unknown command: {}", command), }; let create_interaction_response = command.create_interaction_response(&ctx.http, |response| { response .kind(InteractionResponseType::ChannelMessageWithSource) .interaction_response_data(|message| message.content(response_content)) }); if let Err(why) = create_interaction_response.await { eprintln!("Cannot respond to slash command: {}", why); } } } } ・・・
ready関数にhelloとbyeというコマンドを登録し、
interaction_create関数(登録したコマンドを使ったときのhook)で
コマンドに対するレスポンスを実装します。
それぞれコマンドを受け取ったら、適当なメッセージを返すだけの簡単なものです。
コードが修正できたらrunコマンドを実行してテストしてみます。
% cargo shuttle run Finished dev [unoptimized + debuginfo] target(s) in 2.44s DB ready can be reached at postgres://postgres:postgres@localhost:24660/postgres Starting discord-bot on http://127.0.0.1:8000 DB ready can be reached at postgres://postgres:postgres@localhost:24660/postgres
botがオンラインになりました。
/hello,/byeと登録したコマンドを実行すると、botがメッセージを返してくれます。
なお、ローカルテストでなくshuttleにデプロイしたいならdeployコマンドを実行します。
% cargo shuttle deploy
Summary
今回はRustでDiscordのシンプルなbotを実装して
動作確認してみました。
参考にしたここでは、
このあとさらにいろいろなAPIを使ってbotを実装しているので、
興味のあるかたはチェックしてみてください。